#include "drivers/chip/_hal.h"

#define SYS_LOG_DOMAIN "vm"
#include "sys_log.h"

#include <stdio.h>
#include <termio.h>
#include <unistd.h>

#if defined(MIX_SHELL)
#define _UART_MODE 0 /* 0: 初始化时更改配置；1: 读数据时修改配置 */
#else
#define _UART_MODE 1 /* 0: 初始化时更改配置；1: 读数据时修改配置 */
#endif

#if (_UART_MODE == 0)
static struct termios tm_old;
static uint8_t bak_flag;
#endif

void drv_uart_pin_configure_txd(hal_id_t id, uint8_t pin)
{
}

void drv_uart_pin_configure_rxd(hal_id_t id, uint8_t pin)
{
}

void drv_uart_enable(hal_id_t id)
{
}

void drv_uart_disable(hal_id_t id)
{
}

void drv_uart_init(hal_id_t id, const uart_param_t *param)
{
#if (_UART_MODE == 0)
    if (bak_flag == 0)
    {
        struct termios tm;
        int fd = 0;
        if (tcgetattr(fd, &tm) < 0)
        { // 保存现在的终端设置
            return;
        }
        tm_old = tm;
        cfmakeraw(&tm); // 更改终端设置为原始模式，该模式下所有的输入数据以字节为单位被处理
        if (tcsetattr(fd, TCSANOW, &tm) < 0)
        { // 设置上更改之后的设置
            return;
        }
        bak_flag = 1;
    }
#endif
}

void drv_uart_deinit(hal_id_t id)
{
#if (_UART_MODE == 0)
    int fd = 0;
    if (bak_flag)
    {
        tcsetattr(fd, TCSANOW, &tm_old);
    }
#endif
}

void drv_uart_set_br(hal_id_t id, unsigned clk, unsigned baudrate)
{
    SYS_LOG("");
}

unsigned drv_uart_get_br(hal_id_t id, unsigned clk)
{
    SYS_LOG("");
    return 0;
}

int drv_uart_poll_read(hal_id_t id, void *data)
{
#if (_UART_MODE == 1)
    /* 保存现在的终端设置 */
    struct termios tm;
    if (tcgetattr(0, &tm) < 0)
    {
        return -1;
    }
    struct termios old = tm;

    /* 更改终端设置为原始模式，该模式下所有的输入数据以字节为单位被处理 */
    cfmakeraw(&tm);
    if (tcsetattr(0, TCSANOW, &tm) < 0)
    {
        return -1;
    }
#endif

    /* 读取输入 */
    int ch = getchar();
    int ret = ch < 0;

#if (_UART_MODE == 1)
    /* 恢复设置 */
    if (tcsetattr(0, TCSANOW, &old) < 0)
    {
        return -1;
    }
#endif

    /* 输出数据 */
    if (ret == 0)
    {
        *(char *)data = ch;
        return 1;
    }

    return 0;
}

int drv_uart_poll_write(hal_id_t id, uint8_t data)
{
    putchar(data);
    return 0;
}

int drv_uart_fifo_read(hal_id_t id, void *data, int size)
{
    int ret = 0;
    for (int i = 0; i < size; i++)
    {
        if (drv_uart_poll_read(id, &((char *)data)[i]) <= 0)
        {
            break;
        }
        ++ret;
    }
    return 0;
}

int drv_uart_fifo_fill(hal_id_t id, const void *data, int size)
{
    for (unsigned i = 0; i < size; i++)
    {
        drv_uart_poll_write(id, ((char *)data)[i]);
    }
    return size;
}

int drv_uart_irq_callback_enable(hal_id_t id, uart_isr_cb_fn cb)
{
    SYS_LOG("");
    return -1;
}

int drv_uart_irq_callback_disable(hal_id_t id)
{
    SYS_LOG("");
    return -1;
}

void drv_uart_irq_enable(hal_id_t id, bool rx, bool tx, int priority)
{
    SYS_LOG("");
}

void drv_uart_irq_disable(hal_id_t id, bool rx, bool tx)
{
    SYS_LOG("");
}

bool drv_uart_wait_tx_busy(hal_id_t id)
{
    return false;
}

bool drv_uart_is_tx_ready(hal_id_t id)
{
    return true;
}

bool drv_uart_is_rx_ready(hal_id_t id)
{
    return true;
}
